;===========================================
;硬件启动汇编代码
;===========================================
;汇编启动步骤
;1. 关闭看门狗
;2. 屏蔽系统中断以及子级别中断
;3. 设置CPU频率
;4. 开启LED灯，标志状态
;5. 初始化系统内存控制器，加快反问速度
;6. 设置各种模式下的系统堆栈
;7. 搬迁代码区,RW，ZI区域
;8. 进入系统模式，跳转至主程序开始执行

	GET 2440addr.inc
    GET option.inc

;Pre-defined constants
USERMODE    EQU 	0x10
SYSMODE     EQU 	0x10
FIQMODE     EQU 	0x11
IRQMODE     EQU 	0x12
SVCMODE     EQU 	0x13
ABORTMODE   EQU 	0x17
UNDEFMODE   EQU 	0x1b
MODEMASK    EQU 	0x1f
NOINT       EQU 	0xc0
    
    AREA Startup,CODE,READONLY
    PRESERVE8
    EXPORT	__START
	IMPORT UndefHandler
	IMPORT SWIHandler
	IMPORT PabortHandler
	IMPORT IRQHandler
	IMPORT DabortHandler
	IMPORT FIQHandler
	IMPORT __main
	IMPORT main
	IMPORT led_init
	IMPORT led_dispnum
	IMPORT |Image$$LD_STARTUP$$Base|
	IMPORT |Image$$LD_STARTUP$$Length|
	IMPORT |Image$$LD_RW$$Base|
	IMPORT |Image$$LD_RW$$Length|
	IMPORT |Image$$SVCStack$$ZI$$Base|
	IMPORT |Image$$UndefStack$$ZI$$Base|
	IMPORT |Image$$AbortStack$$ZI$$Base|
	IMPORT |Image$$IRQStack$$ZI$$Base|
	IMPORT |Image$$FIQStack$$ZI$$Base|
	ENTRY
__START
	b ResetHandler		;handler for reset
	b UndefHandler		;handler for Undefined mode
	b SWIHandler		;handler for SWI interrupt
	b PabortHandler	;handler for PAbort
	b DabortHandler	;handler for DAbort
	nop
	b IRQHandler		;handler for IRQ interrupt
	b FIQHandler		;handler for FIQ interrupt
	;0x20
	nop

ResetHandler
    ;1. 关闭看门狗
    ldr r0,=WTCON
    mov r1,#0
    str r1,[r0]

    ;2. 屏蔽所有中断
    ldr r0,=INTMSK
    ldr r1,=0xffffffff    
    str r1,[r0]

    ldr	r0,=INTSUBMSK
	ldr	r1,=0x7fff		;all sub interrupt disable
	str	r1,[r0]

    ;To reduce PLL lock time, adjust the LOCKTIME register.
	ldr	r0,=LOCKTIME
	ldr	r1,=0xffffff
	str		r1,[r0]
    
    ;设置CPU频率
    ldr	r0,=CLKDIVN  
	ldr	r1,=CLKDIV_VAL		; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
	str	r1,[r0]
    ;设置为快总线方式
    [ CLKDIV_VAL>1 		; means Fclk:Hclk is not 1:1.
	mrc p15,0,r0,c1,c0,0
	orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA
	mcr p15,0,r0,c1,c0,0
	|
	mrc p15,0,r0,c1,c0,0
	bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF
	mcr p15,0,r0,c1,c0,0
	]
	;Configure UPLL
	ldr	r0,=UPLLCON
	ldr	r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) 
	str	r1,[r0]

	nop	; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
	nop
	nop
	nop
	nop
	nop
	nop
	;Configure MPLL
	ldr	r0,=MPLLCON
	ldr	r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) 
	str	r1,[r0]
    
    ;打开所有LED灯
    ldr r0,=GPBCON
    ldr r1,[r0]
    mov r2,#0xff
    bic r1,r2,LSL#10
    mov r2,#0x55
    orr r1,r1,r2,LSL#10
    str r1,[r0]
    ldr r0,=GPBDAT
    ldr r1,[r0]
    mov r2,#0xf
    bic r1,r2,LSL#5
    str r1,[r0]
    ;设置内存控制器
    adrl r0,SMRDATA
    ldr r1,=BWSCON
    add r2,r0,#52
0
	ldr	r3, [r0], #4
	str	r3, [r1], #4
	cmp	r2, r0
	bne	%B0

    ;初始化堆栈
    bl InitStacks

	;拷贝数据到SDRAM,NOR启动，NAND启动，调试
copy_proc_beg
	adrl r0,__START
	ldr r1,ROBase
	cmp r0,r1
	beq run_in_ram
	ldr r3,ROLength
	add r3,r3,r1
copy_ro
	ldr r2,[r0]
	add r0,r0,#4
	str r2,[r1]
	add r1,r1,#4
	cmp r1,r3
	bne copy_ro
copy_rw
	ldr r1,RWBase
	ldr r3,RWLength
	add r3,r3,r1
	cmp r1,r3
	beq jump_to_ram
loop_rw
	ldr r2,[r0]
	add r0,r0,#4
	str r2,[r1]
	add r1,r1,#4
	cmp r1,r3
	bne loop_rw
jump_to_ram
	adrl r0,__START
	adrl r1,run_in_ram
	sub r2,r1,r0
	ldr r3,ROBase
	add r2,r2,r3
	bx r2

run_in_ram
    ;跳转至主函数开始执行
	;bic	r0,r0,#(MODEMASK:OR:NOINT)
	;orr	r1,r0,#SYSMODE
	;msr	cpsr_c,r1		;SYS Mode
	ldr r10,=__main
	bx r10
	;bl main
	b .

;turnonled
;	lsl r0,r0,#5
;	ldr r1,=GPBDAT
;	str r0,[r1]
;	mov pc,lr
;初始化堆栈空间
InitStacks
	;Don't use DRAM,such as stmfd,ldmfd......
	;SVCstack is initialized before
	;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
	mrs	r0,cpsr
	bic	r0,r0,#MODEMASK
	orr	r1,r0,#(UNDEFMODE:OR:NOINT)
	msr	cpsr_cxsf,r1		;UndefMode
	ldr	sp,UndefStack

	orr	r1,r0,#(ABORTMODE:OR:NOINT)
	msr	cpsr_cxsf,r1		;AbortMode
	ldr	sp,AbortStack

	orr	r1,r0,#(IRQMODE:OR:NOINT)
	msr	cpsr_cxsf,r1		;IRQMode
	ldr	sp,IRQStack

	orr	r1,r0,#(FIQMODE:OR:NOINT)
	msr	cpsr_cxsf,r1		;FIQMode
	ldr	sp,FIQStack

	bic	r0,r0,#(MODEMASK:OR:NOINT)
	orr	r1,r0,#SVCMODE
	msr	cpsr_cxsf,r1		;SVCMode
	ldr	sp,SVCStack

	;there is no need to set user or sys mode stack
	;because the stack of sysmode or usermode will be set by __main()
	bx	lr
	;The LR register won't be valid if the current mode is not SVC mode.

	LTORG

;GCS0->SST39VF1601
;GCS1->16c550
;GCS2->IDE
;GCS3->CS8900
;GCS4->DM9000
;GCS5->CF Card
;GCS6->SDRAM
;GCS7->unused

SMRDATA DATA
; Memory configuration should be optimized for best performance
; The following parameter is not optimized.
; Memory access cycle parameter strategy
; 1) The memory settings is  safe parameters even at HCLK=75Mhz.
; 2) SDRAM refresh period is for HCLK<=75Mhz.

	DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
	DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0
	DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))   ;GCS1
	DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))   ;GCS2
	DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))   ;GCS3
	DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))   ;GCS4
	DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))   ;GCS5
	DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))    ;GCS6
	DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))    ;GCS7
	DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)

	DCD 0x32	    ;SCLK power saving mode, BANKSIZE 128M/128M

	DCD 0x30	    ;MRSR6 CL=3clk
	DCD 0x30	    ;MRSR7 CL=3clk

ROBase 		DCD |Image$$LD_STARTUP$$Base|
ROLength	DCD |Image$$LD_STARTUP$$Length|
RWBase		DCD	|Image$$LD_RW$$Base|
RWLength	DCD |Image$$LD_RW$$Length|
;The location of stacks
SVCStack	DCD	|Image$$SVCStack$$ZI$$Base|
UndefStack	DCD	|Image$$UndefStack$$ZI$$Base|
AbortStack	DCD	|Image$$AbortStack$$ZI$$Base|
IRQStack	DCD	|Image$$IRQStack$$ZI$$Base|
FIQStack	DCD	|Image$$FIQStack$$ZI$$Base|
	END